package com.ebelter.btlibrary.btble.impl.scale;

import android.os.Handler;
import android.os.HandlerThread;

import com.ebelter.btlibrary.btble.ble.bluetooth.device.impl.BleCommandEditor;
import com.ebelter.btlibrary.btble.ble.model.BtAck;
import com.ebelter.btlibrary.btble.impl.scale.common.ScaleAck;
import com.ebelter.btlibrary.btble.impl.scale.model.ScaleCommand;
import com.ebelter.btlibrary.btble.impl.scale.model.ScaleUser;
import com.ebelter.btlibrary.util.ULog;

import java.util.Arrays;
import java.util.Calendar;

/**
 * 体脂秤指令编辑器实现层
 * Created by Sergio Pan on 2017/12/8.
 */

public class ScaleCommondEditor extends BleCommandEditor {

    private static final String TAG = "ScaleCommondEditor";

    private static ScaleCommondEditor instance = new ScaleCommondEditor();

    //心跳线程用
    private Handler mHandler;
    private long sendDataTime = 0;
    private int sendDataTimeout = 2000;


    //通讯数据是否加密
    private boolean isDataEncrypt = true;
    //
    private byte[] deviceAddressBytes = new byte[]{0x16, 0x15, 0x14, 0x13, 0x12, 0x11};

    private ScaleCommondEditor() {
    }

    public static ScaleCommondEditor getInstance() {
        return instance;
    }

    @Override
    protected byte[] encrypt(byte[] data) {
        ULog.i(TAG, "----encript--- before --data = " + Arrays.toString(data));
        if (isDataEncrypt && (data[0] & 0xff) == (dataHeaderSend&0xff)) {
            byte[] macAddr = deviceAddressBytes;
            for (int i = 3, j = 0; i < data.length; i++, j++) {
                data[i] ^= macAddr[j % 6];
            }
        }
        ULog.i(TAG, "----encript-----data = " + Arrays.toString(data));
        return data;
    }

    /**
     * 设置秤用户信息
     *
     * @param user
     */
    public void setUserInfo(ScaleUser user) {
        ULog.i(TAG, "----setUserInfo-----set user info cmd-----user = " + user);
        sendResquest(new BtAck(ScaleAck.ACK_SET_CUSTOM), user.buildScaleUserData());
    }


    /**
     * 下发删除所有用户指令
     */
    public void requestDelAllUser() {
        ULog.i(TAG, "send delete all user list cmd.");
        byte[] bytes = {
                dataHeaderSend,
                0x02,
                (byte) 0xa1,
                0x00
        };
        sendResquest(new BtAck(ScaleAck.ACK_DELETE_ALL_USER),bytes);
    }


    /**
     * 手机端接收完成后，发给秤的响应，标识已完成接收，防止丢包
     * <p>
     * 下发接收到脂肪测量结果ACK
     */
//    public void sendResultAck() {
////        ULog.i(TAG, "send fat result ack response.");
////        byte[] bytes = {
////                dataHeaderSend,
////                0x02,
////                (byte) 0xa3,
////                0x00
////        };
////        this.onSendBleMessage(bytes);
//    }

    /**
     * 下发同步系统时间命令
     */
    public void syncSystemClock() {
        ULog.i(TAG, "----syncSystemClock-----send sync system time cmd.");
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        int date = cal.get(Calendar.DATE);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        int minute = cal.get(Calendar.MINUTE);
        int second = cal.get(Calendar.SECOND);

//        setClockTime = cal.getTimeInMillis();

        //TODO 需要确认
        //周一至周日，1至7
        int week = cal.get(Calendar.DAY_OF_WEEK);
        week = (week == 1) ? 7 : (week - 1);

        int yearLowHex = year & 0xff;
        int yearHeightHex = (year >> 8) & 0xff;

        ULog.i(TAG,"year="+year+"--yearLowHex="+yearLowHex+"--yearHeightHex="+yearHeightHex+"--month="+month
                +"--date="+date+"--hour="+hour+"--minute="+minute+"--second="+second+"--week="+week);
        byte[] bytes = {
                dataHeaderSend,
                0x09,
                (byte) 0x98,
                (byte) yearLowHex,
                (byte) yearHeightHex,
                (byte) month,
                (byte) date,
                (byte) hour,
                (byte) minute,
                (byte) second,
                (byte) week

        };

        sendResquest(new BtAck(ScaleAck.ACK_SET_CLOCK), bytes);
    }


    /**
     * 请求历史记录
     *
     * @param uid
     */
    public void requestHistoryRecords(String uid) {
        ULog.i(TAG, "----requestHistoryRecords-----request History Records cmd, uid is : " + uid);
        String[] uidArr = uid.split(":");

        if (uidArr.length != 7) {
            uidArr = new String[]{"0", "0", "0", "0", "0", "0", "0"};
        }

        byte[] bytes = {
                dataHeaderSend,
                0x07,
                (byte) 0x9b,
                (byte) Integer.parseInt(uidArr[0], 16),
                (byte) Integer.parseInt(uidArr[1], 16),
                (byte) Integer.parseInt(uidArr[2], 16),
                (byte) Integer.parseInt(uidArr[3], 16),
                (byte) Integer.parseInt(uidArr[4], 16),
                (byte) Integer.parseInt(uidArr[5], 16),
                (byte) Integer.parseInt(uidArr[6], 16),
                0x00
        };
        ULog.i(TAG, "------requestHistoryRecords------ cmd = " + Arrays.toString(bytes));
        sendResquest(new BtAck(ScaleAck.ACK_GET_RECOED), bytes);
    }

    /**
     * 下发查询版本
     */
    public void requestScaleVersion() {
        ULog.i(TAG, "----requestScaleVersion------send get version cmd.");
        byte[] bytes = {
                dataHeaderSend,
                0x01,
                (byte) 0x9c
        };
        sendResquest(new BtAck(ScaleAck.ACK_GET_VERSION),bytes);
    }

    /**
     * 下发OTA分包数据
     * 2017-02-11
     *
     * @param bs    数据包内容
     * @param pkgNo 第N个包
     */
    public void sendOTAPackage(byte[] bs, int pkgNo) {
        ULog.i(TAG, "-----sendOTAPackage----send ota package data cmd.");
        int bsLen = bs.length;
        ULog.i(TAG, "pkg data len:" + bsLen + ",data is : " + Arrays.toString(bs));
        //包号，总包数大，一个字节存不完，需分高8位，低8位
        int noLowHex = pkgNo & 0xff;
        int noHeightHex = (pkgNo >> 8) & 0xff;
        //bytes为传输的数据包，第0个字节为包头，第1个为指令，第2--3个为包号，
        byte[] bytes = new byte[20];
        bytes[0] = (byte) 0xad;
        bytes[1] = (byte) 0x12;
        bytes[2] = (byte) noLowHex;
        bytes[3] = (byte) noHeightHex;

        //第4--19个为数据，数据长度不够16，则用0xff填充
        for (int i = 4, j = 0; i < 20; i++, j++) {
            if (j >= bsLen) {
                bytes[i] = (byte) 0xff;
            } else {
                bytes[i] = bs[j];
            }
        }


        //后18位做xor亦或校验，存入bytes[1]
        byte csXor = 0;
        for (int i = 2; i < bytes.length; i++) {
            csXor ^= bytes[i];
        }
        bytes[1] = csXor;
        //Fat Body协议修改
        bytes[2] = (byte) (((pkgNo & 0xff) + 0x90) & 0xff);
//		bytes[21] = 0x11;
//		bytes[22] = 0x00;

        sendResquest(new BtAck(ScaleAck.ACK_SET_OTA), bytes);
    }


    //下发OTA请求升级(2017-05-05新增，crc8校验）

    /**
     *
     * @param type   01:蓝牙固件,02：秤固件
     * @param pkgLen 整包长度
     * @param cs  CRC8校验值
     */
    public void sendOTAUpdateRequestCRC(int type, int pkgLen, int cs) {
        ULog.i(TAG, "send ota updarge request cmd. cs:" + Integer.toHexString(cs));
        int lenLowHex = pkgLen & 0xff;
        int lenHeightHex = (pkgLen >> 8) & 0xff;

        byte[] bytes = {
                dataHeaderSend,
                0x06,
                (byte) 0x9d,
                (byte) type,
                (byte) lenLowHex,
                (byte) lenHeightHex,
                (byte) cs,
                0
        };

        sendResquest(new BtAck(ScaleAck.ACK_GET_OTA_UPGRADE_REQ),bytes);
    }


    /**
     * 开始发送心跳包
     */
    public void startConnHeartbeat() {
        ULog.i(TAG, "-----startConnHeartbeat----");
        if (mHandler == null) {
            HandlerThread handlerThread = new HandlerThread("ScaleCommondEditor");
            handlerThread.start();
            mHandler = new Handler(handlerThread.getLooper());
        }
        mHandler.removeCallbacks(heartbeatRunnable);

        mHandler.post(heartbeatRunnable);
    }

    /**
     * 停止心跳
     */
    public void stopConnHeartbeat() {
        if (mHandler != null) {
            mHandler.removeCallbacks(heartbeatRunnable);
        }
    }

    /**
     * 心跳线程
     */
    Runnable heartbeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendDataTime > sendDataTimeout) {
                sendHeartBeatCmd();
            }
            mHandler.postDelayed(this, 500);
        }
    };

    /**
     * 下发心跳指令
     */
    public void sendHeartBeatCmd() {
        ULog.d(TAG, "send bt heartbeat cmd.");

        byte[] bytes = {
                dataHeaderSend,
                0x01,
                (byte) 0xb0
        };

        this.sendBleMessage(bytes);
    }




    @Override
    protected void onReceiveCommand(Object command) {
        ScaleCommand scaleCommand = (ScaleCommand) command;
        ULog.i(TAG, "-------onReceiveCommand-------scaleCommand = " + scaleCommand);
        switch (scaleCommand) {
            case SYNC_CLOCK:    //同步时钟
                syncSystemClock();
                break;
                case HEART_BEART:    //发心跳
                startConnHeartbeat();
                break;
//            case SET_USER_INFO:     //设置用户信息
//                ScaleUser user = ScaleUser.getUser();
//                if (user != null && user.getBtId() != null) {
//                    setUserInfo(user);
//                }
         //       break;
            case REQUEST_HISTORY_DATA:  //请求历史数据
                break;
        }
    }

    private static final byte[] getHistoryDataACK= {(byte) 0xab, 0x02, (byte) 0x9b, 0x01};
    public void sendGetHistoryACK() {//历史数据的ACK
        ULog.i(TAG,"历史数据---回ack");
        sendResquest2(new BtAck(ScaleAck.ACK_GET_HISTORY), getHistoryDataACK);
    }
    private static final byte[] getMesureDataACK= {(byte) 0xab, 0x02, (byte) 0xa3, 0x00};
    public void sendMesureACK() {
        ULog.i(TAG,"测量---回ack");
        sendResquest2(new BtAck(ScaleAck.ACK_GET_LAST_MEASURE), getMesureDataACK);
    }
}
